package com.colabo.j2ee.web.core.pkgenerator;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Date;

import com.colabo.j2ee.web.core.exception.CommonException;
import com.colabo.j2ee.web.core.exception.ReadableMessage;
import com.colabo.j2ee.web.core.exception.ServiceException;
import com.colabo.j2ee.web.core.service.impl.DefaultServiceImpl;
import com.colabo.j2ee.web.core.util.UUIDGenerator;
import com.colabo.j2ee.web.core.vo.KeyGenVO;

/**
 * Default implementation of the PK Generator
 * @author Anthony Do
 * @since 2009-12-23
 *
 */
public class DefaultPKGenerator extends DefaultServiceImpl implements IPKGenerator {

	private static int DEFAULT_STEP = 1000;
	private static Long LONGKEY_SEED = new Long(0);
	// 因为spring注入时整数只能转为int, 因此在这里step用int
	private int step = DEFAULT_STEP;
	private Long currentKey = new Long(-1);
	private Long maxKey = new Long(-1);

	public synchronized Long getLongKey() throws ServiceException {
		Long rv = new Long(-1);		
		Connection  conn = null;
		try {
			
			String querySql  = "SELECT KEYVALUE FROM IP_KEYGEN WHERE NODEID=0 FOR UPDATE";
			String updateSql = "UPDATE IP_KEYGEN SET KEYVALUE=KEYVALUE+1 WHERE NODEID=0";
			String insertSql = "INSERT INTO IP_KEYGEN(NODEID,KEYVALUE,RECORDSTATE)VALUES(0,1,1)";
			conn = getJdbcTemplate().getDataSource().getConnection();
			conn.setAutoCommit(false);
			Statement st = conn.createStatement();
			Statement st2 = conn.createStatement();
			
			ResultSet rs = st.executeQuery(querySql);
			if(rs.next()){
				long tmp = rs.getLong(1);
				rv = new Long(tmp+1);				
			}else{
				st2.execute(insertSql);
				rv = new Long(0);		
			}			
			
			st.execute(updateSql);
			conn.commit();
			st.close();
			st2.close();
		} catch (Exception e) {
			try {conn.rollback();} catch (SQLException ex) {	}
			throw new ServiceException(e.getMessage());
		}finally{
			if(null!=conn){try {conn.close();} catch (SQLException e) {	}}
		}
		
		if(rv.longValue()<0){
			throw new ServiceException("Can't get value!");
		}
		
		return rv;
	}
	
	protected void saveKey() throws ServiceException {
		maxKey = new Long(maxKey.longValue() + step);
		try {
			KeyGenVO keyGenVo = (KeyGenVO) findByID_Hibernate_Get(KeyGenVO.class, LONGKEY_SEED);
			if (keyGenVo != null) {
				keyGenVo.setKeyValue(maxKey);
				update_Hibernate_Object(keyGenVo);
			} else { // 若执行中间数据库被清掉, 可以重新初始化主键数据
				keyGenVo = new KeyGenVO();
				keyGenVo.setObjectLongId(LONGKEY_SEED);
				keyGenVo.setRecordState(new Long(0));
				keyGenVo.setKeyValue(maxKey);
				try {
					save_Hibernate_Object(keyGenVo);
				} catch (ServiceException e) {
					throw new ServiceException(new ReadableMessage(""), e);
				}
			}
		} catch (ServiceException e) {
			throw new ServiceException(new ReadableMessage(""), e);
		}
	}

	protected void initKey() throws CommonException {
		KeyGenVO keyGenVo = null;
		try {
			keyGenVo = (KeyGenVO) findByID_Hibernate_Get(KeyGenVO.class, LONGKEY_SEED);
			if (keyGenVo == null) {
				currentKey = new Long(0);
			} else {
				currentKey = keyGenVo.getKeyValue();
			}
		} catch (ServiceException e) {
			throw new CommonException(new ReadableMessage(""), e);
		}
		maxKey = currentKey;
	}
	

	public String getUUIDKey() throws ServiceException {
		return UUIDGenerator.generate(new Date());
	}

	public String getUUIDKey(Object obj) throws ServiceException {
		return UUIDGenerator.generate(obj);
	}
	
}
